/*
* ModeShape (http://www.modeshape.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.modeshape.jcr;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import javax.jcr.Binary;
import javax.jcr.ItemNotFoundException;
import javax.jcr.NoSuchWorkspaceException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.lock.LockManager;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.nodetype.NodeTypeTemplate;
import javax.jcr.query.Query;
import javax.jcr.security.AccessControlList;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.AccessControlPolicyIterator;
import javax.jcr.security.Privilege;
import javax.jcr.version.Version;
import javax.jcr.version.VersionException;
import javax.jcr.version.VersionHistory;
import javax.jcr.version.VersionIterator;
import javax.jcr.version.VersionManager;
import javax.transaction.TransactionManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.modeshape.common.FixFor;
import org.modeshape.common.util.FileUtil;
import org.modeshape.common.util.IoUtil;
import org.modeshape.connector.mock.MockConnector;
import org.modeshape.jcr.api.BackupOptions;
import org.modeshape.jcr.api.JcrConstants;
import org.modeshape.jcr.api.NamespaceRegistry;
import org.modeshape.jcr.api.Problems;
import org.modeshape.jcr.api.RestoreOptions;
import org.modeshape.jcr.api.Workspace;
import org.modeshape.jcr.api.federation.FederationManager;
import org.modeshape.jcr.security.SimplePrincipal;
import org.modeshape.jcr.value.Path;
public class ModeshapePersistenceIT {
private static final String[] BINARY_RESOURCES = new String[] { "data/large-file1.png",
"data/move-initial-data.xml",
"data/simple.json",
"data/singleNode.json" };
private final TestRepository testRepository = new TestRepository();
private File backupArea;
private File backupDirectory;
private File backupDirectory2;
private File backupRepoDir;
@Before
public void beforeEach() throws Exception {
backupArea = new File("target/backupArea");
FileUtil.delete(backupArea.getPath());
//use a UUID for the backup folder to prevent some file locks lingering between tests
String folderId = UUID.randomUUID().toString();
backupDirectory = new File(backupArea, "repoBackups_" + folderId);
backupDirectory2 = new File(backupArea, "repoBackupsAfter_" + folderId);
backupDirectory.mkdirs();
backupDirectory2.mkdirs();
backupRepoDir = new File(backupArea, "backupRepo");
backupRepoDir.mkdirs();
new File(backupArea, "restoreRepo").mkdirs();
FileUtil.delete("target/startup_test_indexes");
}
@After
public void afterEach() throws Exception {
testRepository.setDropOnExit(true);
testRepository.shutdown();
this.cleanDatabase();
}
@Test
public void shouldKeepPersistentDataAcrossRestart() throws Exception {
startRunStop(repository -> {
Session session = repository.login();
session.getRootNode().addNode("testNode");
session.save();
// create 2 new workspaces
session.getWorkspace().createWorkspace("ws1");
session.getWorkspace().createWorkspace("ws2");
session.logout();
}, true, false);
startRunStop(repository -> {
Session session = repository.login();
assertNotNull(session.getNode("/testNode"));
session.logout();
// check the workspaces were persisted
Session newWsSession = repository.login("ws1");
newWsSession.getRootNode().addNode("newWsTestNode");
newWsSession.save();
newWsSession.logout();
Session newWs1Session = repository.login("ws2");
newWs1Session.getWorkspace().deleteWorkspace("ws2");
newWs1Session.logout();
}, false, false);
startRunStop(repository -> {
Session newWsSession = repository.login("ws1");
assertNotNull(newWsSession.getNode("/newWsTestNode"));
newWsSession.logout();
// check a workspace was deleted
try {
repository.login("ws2");
fail("Workspace was not deleted from the repository");
} catch (NoSuchWorkspaceException e) {
// expected
}
}, false, true);
}
@Test
public void shouldNotImportInitialContentIfWorkspaceContentsChanged() throws Exception {
startRunStop(repository -> {
Session ws1Session = repository.login();
// check the initial import
Node node = ws1Session.getNode("/a");
assertNotNull(node);
// remove the node initially imported and add a new one
node.remove();
ws1Session.getRootNode().addNode("testNode");
ws1Session.save();
}, true, false);
startRunStop(repository -> {
Session ws1Session = repository.login();
try {
ws1Session.getNode("/a");
fail("The initial content should be be re-imported if a workspace is not empty");
} catch (PathNotFoundException e) {
// expected
}
ws1Session.getNode("/testNode");
}, false, true);
}
@Test
public void shouldPersistExternalProjectionToFederatedNodeMappings() throws Exception {
startRunStop(repository -> {
Session session = repository.login();
Node testRoot = session.getRootNode().addNode("testRoot");
session.save();
FederationManager federationManager = ((Workspace) session.getWorkspace()).getFederationManager();
federationManager.createProjection("/testRoot", "mock-source", MockConnector.DOC1_LOCATION, "federated1");
federationManager.createProjection("/testRoot", "mock-source", MockConnector.DOC2_LOCATION, null);
Node doc1Federated = session.getNode("/testRoot/federated1");
assertNotNull(doc1Federated);
assertEquals(testRoot.getIdentifier(), doc1Federated.getParent().getIdentifier());
}, true, false);
startRunStop(repository -> {
Session session = repository.login();
Node testRoot = session.getNode("/testRoot");
assertNotNull(testRoot);
Node doc1Federated = session.getNode("/testRoot/federated1");
assertNotNull(doc1Federated);
// assertNotNull(doc1Federated.getParent());
// assertEquals(testRoot.getIdentifier(), doc1Federated.getParent().getIdentifier());
Node doc2Federated = session.getNode("/testRoot" + MockConnector.DOC2_LOCATION);
assertNotNull(doc2Federated);
// assertEquals(testRoot.getIdentifier(), doc2Federated.getParent().getIdentifier());
}, false, true);
}
@Test
public void shouldKeepPreconfiguredProjectionsAcrossRestart() throws Exception {
RepositoryOperation checkPreconfiguredProjection = repository -> {
Session session = repository.login();
assertNotNull(session.getNode("/preconfiguredProjection"));
};
startRunStop(checkPreconfiguredProjection, true, false);
startRunStop(checkPreconfiguredProjection, false, true);
}
@Test
public void shouldCleanStoredProjectionsIfNodesAreDeleted() throws Exception {
startRunStop(repository -> {
Session session = repository.login();
session.getRootNode().addNode("testRoot");
session.save();
FederationManager federationManager = ((Workspace) session.getWorkspace()).getFederationManager();
federationManager.createProjection("/testRoot", "mock-source", MockConnector.DOC1_LOCATION, "federated1");
federationManager.createProjection("/testRoot", "mock-source", MockConnector.DOC2_LOCATION, "federated2");
Node projection = session.getNode("/testRoot/federated1");
assertNotNull(projection);
projection.remove();
session.save();
}, true, false);
startRunStop(repository -> {
Session session = repository.login();
// check the 2nd projection
assertNotNull(session.getNode("/testRoot/federated2"));
try {
session.getNode("/testRoot/federated1");
fail("Projection has not been cleaned up");
} catch (PathNotFoundException e) {
// expected
}
}, false, true);
}
@Test
public void shouldAppendJournalEntriesBetweenRestarts() throws Exception {
final List<Integer> recordsOnStartup = new ArrayList<>(2);
RepositoryOperation operation = repository -> {
Session session = repository.login();
session.getRootNode().addNode("node1");
session.save();
session.logout();
Thread.sleep(100);
int records = repository.runningState().journal().allRecords(false).size();
assertTrue(records > 0);
recordsOnStartup.add(records);
};
startRunStop(operation, true, false);
startRunStop(operation, false, true);
int countFirstTime = recordsOnStartup.get(0);
int countSecondTime = recordsOnStartup.get(1);
assertTrue(countSecondTime > countFirstTime);
}
@Test
public void shouldAllowChangingNamespacePrefixesInSession() throws Exception {
final String prefix = "admb";
final String uri = "http://www.admb.be/modeshape/admb/1.0";
final String nodeTypeName = prefix + ":test";
startRunStop(repository -> {
Session session = repository.login();
NodeTypeManager nodeTypeManager = session.getWorkspace().getNodeTypeManager();
// First create a namespace for the nodeType which is going to be added
session.getWorkspace().getNamespaceRegistry().registerNamespace(prefix, uri);
// Start creating a nodeTypeTemplate, keep it basic.
NodeTypeTemplate nodeTypeTemplate = nodeTypeManager.createNodeTypeTemplate();
nodeTypeTemplate.setName(nodeTypeName);
nodeTypeManager.registerNodeType(nodeTypeTemplate, false);
session.getRootNode().addNode("testNode", nodeTypeName);
session.save();
Node node = session.getNode("/testNode");
assertEquals(nodeTypeName, node.getPrimaryNodeType().getName());
session.setNamespacePrefix("newPrefix", uri);
assertEquals("newPrefix:test", node.getPrimaryNodeType().getName());
}, true, false);
startRunStop(repository -> {
Session session = repository.login();
Node node = session.getNode("/testNode");
assertEquals(nodeTypeName, node.getPrimaryNodeType().getName());
}, false, true);
}
@Test
public void reindexingLocalProviderShouldRemoveExistingDataFirst() throws Exception {
startRunStop(repository -> {
JcrSession session = repository.login();
session.getRootNode().addNode("testRoot");
session.save();
Thread.sleep(100);
String sql = "select [jcr:path] from [nt:unstructured] where [jcr:name] = 'testRoot'";
Query query = session.getWorkspace().getQueryManager().createQuery(sql, Query.JCR_SQL2);
ValidateQuery.validateQuery().rowCount(1).useIndex("nodesByName").validate(query, query.execute());
session.logout();
}, true, false);
startRunStop(repository -> {
JcrSession session = repository.login();
// force a re-index of the entire workspace - this should clear the existing indexes first
session.getWorkspace().reindex();
// then force a reindex of a certain path
session.getWorkspace().reindex("/testRoot");
//then check that still only 1 node is returned
String sql = "select [jcr:path] from [nt:unstructured] where [jcr:name] = 'testRoot'";
Query query = session.getWorkspace().getQueryManager().createQuery(sql, Query.JCR_SQL2);
ValidateQuery.validateQuery().rowCount(1).useIndex("nodesByName").validate(query, query.execute());
}, false, true);
}
@Test
public void shouldDisableACLsIfAllPoliciesAreRemoved() throws Exception {
startRunStop(repository -> {
Session session = repository.login();
Node testNode = session.getRootNode().addNode("testNode");
testNode.addNode("node1");
testNode.addNode("node2");
session.save();
AccessControlManager acm = session.getAccessControlManager();
AccessControlList aclNode1 = getACL(acm, "/testNode/node1");
aclNode1.addAccessControlEntry(SimplePrincipal.newInstance("anonymous"),
new Privilege[]{acm.privilegeFromName(Privilege.JCR_ALL)});
acm.setPolicy("/testNode/node1", aclNode1);
AccessControlList aclNode2 = getACL(acm, "/testNode/node2");
aclNode2.addAccessControlEntry(SimplePrincipal.newInstance("anonymous"),
new Privilege[]{acm.privilegeFromName(Privilege.JCR_ALL)});
acm.setPolicy("/testNode/node2", aclNode2);
// access control should not be enabled yet because we haven't saved the session
assertFalse(repository.runningState().repositoryCache().isAccessControlEnabled());
session.save();
assertTrue(repository.runningState().repositoryCache().isAccessControlEnabled());
}, true, false);
startRunStop(repository -> {
assertTrue(repository.runningState().repositoryCache().isAccessControlEnabled());
Session session = repository.login();
AccessControlManager acm = session.getAccessControlManager();
acm.removePolicy("/testNode/node1", null);
acm.removePolicy("/testNode/node2", null);
session.save();
assertFalse(repository.runningState().repositoryCache().isAccessControlEnabled());
session.getNode("/testNode").remove();
session.save();
}, false, true);
}
@Test
public void shouldUseIndexesAfterRestarting() throws Exception {
startRunStop(repository -> {
JcrSession session = repository.login();
session.getRootNode().addNode("testRoot");
session.save();
Thread.sleep(100);
String sql = "select [jcr:path] from [nt:unstructured] where [jcr:name] = 'testRoot'";
Query query = session.getWorkspace().getQueryManager().createQuery(sql, Query.JCR_SQL2);
ValidateQuery.validateQuery().rowCount(1).useIndex("nodesByName").validate(query, query.execute());
session.logout();
}, true, false);
startRunStop(repository -> {
JcrSession session = repository.login();
String sql = "select [jcr:path] from [nt:unstructured] where [jcr:name] = 'testRoot'";
Query query = session.getWorkspace().getQueryManager().createQuery(sql, Query.JCR_SQL2);
ValidateQuery.validateQuery().rowCount(1).useIndex("nodesByName").validate(query, query.execute());
session.logout();
}, false, true);
}
@Test
public void shouldHaveVersionHistoryWhenRefreshIsCalled() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager vm = session.versionManager();
Node outerNode = session.getRootNode().addNode("outerFolder");
Node innerNode = outerNode.addNode("innerFolder");
Node fileNode = innerNode.addNode("testFile.dat");
fileNode.setProperty("jcr:mimeType", "text/plain");
fileNode.setProperty("jcr:data", "Original content");
session.save();
assertFalse(hasVersionHistory(vm, fileNode));
fileNode.addMixin("mix:versionable");
// Version history is not created until save
assertFalse(hasVersionHistory(vm, fileNode));
session.refresh(true);
// Version history is not created until save
assertFalse(hasVersionHistory(vm, fileNode));
session.save();
assertTrue(hasVersionHistory(vm, fileNode));
}, true, false);
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager vm = session.versionManager();
Node fileNode = session.getNode("/outerFolder/innerFolder/testFile.dat");
assertTrue(hasVersionHistory(vm, fileNode));
}, false, true);
}
@Test
public void shouldAllowAddingUnderCheckedInNodeNewChildNodeWithOpvOfIgnore() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager vm = session.versionManager();
// Set up parent node and check it in ...
Node parent = session.getRootNode().addNode("versionableNode", "ver:versionable");
parent.setProperty("versionProp", "v");
parent.setProperty("copyProp", "c");
parent.setProperty("ignoreProp", "i");
session.save();
vm.checkin(parent.getPath());
// Try to add child with OPV of ignore ...
Node child = parent.addNode("nonVersionedIgnoredChild", "ver:nonVersionableChild");
child.setProperty("copyProp", "c");
child.setProperty("ignoreProp", "i");
session.save();
// Try to update the properties on the child with OPV of 'ignore'
child.setProperty("copyProp", "c2");
child.setProperty("ignoreProp", "i2");
session.save();
// Try to add versionable child with OPV of ignore ...
Node child2 = parent.addNode("versionedIgnoredChild", "ver:versionableChild");
child2.setProperty("copyProp", "c");
child2.setProperty("ignoreProp", "i");
session.save();
// Try to update the properties on the child with OPV of 'ignore'
child2.setProperty("copyProp", "c2");
child2.setProperty("ignoreProp", "i2");
session.save();
}, true, true);
}
@Test
public void shouldNotAllowAddingUnderCheckedInNodeNewChildNodeWithOpvOfSomethingOtherThanIgnore() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager vm = session.versionManager();
// Set up parent node and check it in ...
Node parent = session.getRootNode().addNode("versionableNode", "ver:versionable");
parent.setProperty("versionProp", "v");
parent.setProperty("copyProp", "c");
parent.setProperty("ignoreProp", "i");
session.save();
vm.checkin(parent.getPath());
// Try to add versionable child with OPV of not ignore ...
try {
parent.addNode("versionedChild", "ver:versionableChild");
fail("should have failed");
} catch (VersionException e) {
// expected
}
// Try to add non-versionable child with OPV of not ignore ...
try {
parent.addNode("nonVersionedChild", "ver:nonVersionableChild");
fail("should have failed");
} catch (VersionException e) {
// expected
}
}, true, true);
}
@Test
public void shouldAllowRemovingFromCheckedInNodeExistingChildNodeWithOpvOfIgnore() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager vm = session.versionManager();
// Set up parent node and check it in ...
Node parent = session.getRootNode().addNode("versionableNode", "ver:versionable");
parent.setProperty("versionProp", "v");
parent.setProperty("copyProp", "c");
parent.setProperty("ignoreProp", "i");
Node child1 = parent.addNode("nonVersionedIgnoredChild", "ver:nonVersionableChild");
child1.setProperty("copyProp", "c");
child1.setProperty("ignoreProp", "i");
Node child2 = parent.addNode("versionedIgnoredChild", "ver:versionableChild");
child2.setProperty("copyProp", "c");
child2.setProperty("ignoreProp", "i");
session.save();
vm.checkin(parent.getPath());
// Should be able to change the properties on the ignored children
child1.setProperty("copyProp", "c2");
child1.setProperty("ignoreProp", "i2");
child2.setProperty("copyProp", "c2");
child2.setProperty("ignoreProp", "i2");
session.save();
// Try to remove the two child nodes that have an OPV of 'ignore' ...
child1.remove();
child2.remove();
session.save();
// Should be able to change the ignored properties on the checked-in parent ...
parent.setProperty("ignoreProp", "i");
// Should not be able to set any non-ignored properties on the checked in parent ...
try {
parent.setProperty("copyProp", "c2");
fail("not allowed");
} catch (VersionException e) {
// expected
}
try {
parent.setProperty("versionProp", "v2");
fail("not allowed");
} catch (VersionException e) {
// expected
}
}, true, true);
}
@Test
public void shouldNotAllowRemovingFromCheckedInNodeExistingChildNodeWithOpvOfSomethingOtherThanIgnore() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager vm = session.versionManager();
// Set up parent node and check it in ...
Node parent = session.getRootNode().addNode("versionableNode", "ver:versionable");
parent.setProperty("versionProp", "v");
parent.setProperty("copyProp", "c");
parent.setProperty("ignoreProp", "i");
Node child1 = parent.addNode("nonVersionedChild", "ver:nonVersionableChild");
child1.setProperty("copyProp", "c");
child1.setProperty("ignoreProp", "i");
Node child2 = parent.addNode("versionedChild", "ver:versionableChild");
child2.setProperty("copyProp", "c");
child2.setProperty("ignoreProp", "i");
session.save();
vm.checkin(parent.getPath());
vm.checkin(child2.getPath());
// Should not be able to set any non-ignored properties on the checked in parent ...
try {
parent.setProperty("copyProp", "c2");
fail("not allowed");
} catch (VersionException e) {
// expected
}
try {
parent.setProperty("versionProp", "v2");
fail("not allowed");
} catch (VersionException e) {
// expected
}
// Should not be able to set any non-ignored properties on the non-ignored children ...
try {
child2.setProperty("copyProp", "c2");
fail("not allowed");
} catch (VersionException e) {
// expected
}
try {
child1.setProperty("copyProp", "c2");
fail("not allowed");
} catch (VersionException e) {
// expected
}
// Check out the versionable child node, and we should be able to edit it ...
vm.checkout(child2.getPath());
child2.setProperty("copyProp", "c3");
session.save();
vm.checkin(child2.getPath());
// But we still cannot edit a property on the nonVersionable child node when the parent is still checked in ...
try {
child1.setProperty("copyProp", "c2");
fail("not allowed");
} catch (VersionException e) {
// expected
}
// Check out the parent ...
vm.checkout(parent.getPath());
// Now we can change the properties on the non-versionable children ...
child1.setProperty("copyProp", "c2");
session.save();
// And even remove it ...
child1.remove();
session.save();
// Check in the parent ...
vm.checkin(parent.getPath());
// and we cannot remove the child versionable node ...
try {
child2.remove();
fail("not allowed");
} catch (VersionException e) {
// expected
}
// But once the parent is checked out ...
vm.checkout(parent.getPath());
// We can remove the versionable child that is checked in (!), since the parent is checked out ...
// See Section 15.2.2:
// "Note that remove of a read-only node is possible, as long as its parent is not read-only,
// since removal is an alteration of the parent node."
assertThat(vm.isCheckedOut(child2.getPath()), is(false));
child2.remove();
session.save();
}, true, true);
}
@Test
public void shouldAllowRemovingVersionFromVersionHistory() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
Node outerNode = session.getRootNode().addNode("outerFolder");
Node innerNode = outerNode.addNode("innerFolder");
Node fileNode = innerNode.addNode("testFile.dat");
fileNode.setProperty("jcr:mimeType", "text/plain");
fileNode.setProperty("jcr:data", "Original content");
session.save();
fileNode.addMixin("mix:versionable");
session.save();
// Make several changes ...
String path = fileNode.getPath();
for (int i = 2; i != 7; ++i) {
versionManager.checkout(path);
fileNode.setProperty("jcr:data", "Original content " + i);
session.save();
versionManager.checkin(path);
}
// Get the version history ...
VersionHistory history = versionManager.getVersionHistory(path);
assertThat(history, is(notNullValue()));
assertThat(history.getAllLinearVersions().getSize(), is(6L));
// Get the versions ...
VersionIterator iter = history.getAllLinearVersions();
Version v1 = iter.nextVersion();
Version v2 = iter.nextVersion();
Version v3 = iter.nextVersion();
Version v4 = iter.nextVersion();
Version v5 = iter.nextVersion();
Version v6 = iter.nextVersion();
assertThat(iter.hasNext(), is(false));
String versionName = v3.getName();
assertThat(v1, is(notNullValue()));
assertThat(v2, is(notNullValue()));
assertThat(v3, is(notNullValue()));
assertThat(v4, is(notNullValue()));
assertThat(v5, is(notNullValue()));
assertThat(v6, is(notNullValue()));
// Remove the 3rd version (that is, i=3) ...
history.removeVersion(versionName);
assertThat(history.getAllLinearVersions().getSize(), is(5L));
// Get the versions using the history node we already have ...
iter = history.getAllLinearVersions();
Version v1a = iter.nextVersion();
Version v2a = iter.nextVersion();
Version v4a = iter.nextVersion();
Version v5a = iter.nextVersion();
Version v6a = iter.nextVersion();
assertThat(iter.hasNext(), is(false));
assertThat(v1a.getName(), is(v1.getName()));
assertThat(v2a.getName(), is(v2.getName()));
assertThat(v4a.getName(), is(v4.getName()));
assertThat(v5a.getName(), is(v5.getName()));
assertThat(v6a.getName(), is(v6.getName()));
// Get the versions using a fresh history node ...
VersionHistory history2 = versionManager.getVersionHistory(path);
assertThat(history.getAllLinearVersions().getSize(), is(5L));
iter = history2.getAllLinearVersions();
Version v1b = iter.nextVersion();
Version v2b = iter.nextVersion();
Version v4b = iter.nextVersion();
Version v5b = iter.nextVersion();
Version v6b = iter.nextVersion();
assertThat(iter.hasNext(), is(false));
assertThat(v1b.getName(), is(v1.getName()));
assertThat(v2b.getName(), is(v2.getName()));
assertThat(v4b.getName(), is(v4.getName()));
assertThat(v5b.getName(), is(v5.getName()));
assertThat(v6b.getName(), is(v6.getName()));
}, true, true);
}
@Test
public void shouldAllowRemovingVersionFromVersionHistoryByRemovingVersionNode() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
Node outerNode = session.getRootNode().addNode("outerFolder");
Node innerNode = outerNode.addNode("innerFolder");
Node fileNode = innerNode.addNode("testFile.dat");
fileNode.setProperty("jcr:mimeType", "text/plain");
fileNode.setProperty("jcr:data", "Original content");
session.save();
fileNode.addMixin("mix:versionable");
session.save();
// Make several changes ...
String path = fileNode.getPath();
for (int i = 2; i != 7; ++i) {
versionManager.checkout(path);
fileNode.setProperty("jcr:data", "Original content " + i);
session.save();
versionManager.checkin(path);
}
// Get the version history ...
VersionHistory history = versionManager.getVersionHistory(path);
assertThat(history, is(notNullValue()));
assertThat(history.getAllLinearVersions().getSize(), is(6L));
// Get the versions ...
VersionIterator iter = history.getAllLinearVersions();
Version v1 = iter.nextVersion();
Version v2 = iter.nextVersion();
Version v3 = iter.nextVersion();
Version v4 = iter.nextVersion();
Version v5 = iter.nextVersion();
Version v6 = iter.nextVersion();
assertThat(iter.hasNext(), is(false));
assertThat(v1, is(notNullValue()));
assertThat(v2, is(notNullValue()));
assertThat(v3, is(notNullValue()));
assertThat(v4, is(notNullValue()));
assertThat(v5, is(notNullValue()));
assertThat(v6, is(notNullValue()));
// Remove the 3rd version (that is, i=3) ...
// history.removeVersion(versionName);
try {
v3.remove();
fail("Should not allow removing a protected node");
} catch (ConstraintViolationException e) {
// expected
}
}, true, true);
}
@SuppressWarnings("deprecation")
@Test
public void shouldFindVersionNodeByIdentifierAndByUuid() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
// Set up parent node and check it in ...
Node parent = session.getRootNode().addNode("versionableNode", "ver:versionable");
parent.setProperty("versionProp", "v");
parent.setProperty("copyProp", "c");
parent.setProperty("ignoreProp", "i");
session.save();
Version version = versionManager.checkin(parent.getPath());
// Now look for the version node by identifier, using the different ways to get an identifier ...
assertThat(session.getNodeByIdentifier(version.getIdentifier()), is((Node) version));
assertThat(session.getNodeByIdentifier(version.getProperty("jcr:uuid").getString()), is((Node) version));
assertThat(session.getNodeByUUID(version.getProperty("jcr:uuid").getString()), is((Node) version));
}, true, true);
}
@Test
public void shouldMergeWorkspaces() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
session.getWorkspace().createWorkspace("original");
session = repository.login("original");
Node root = session.getRootNode();
Node parent1 = root.addNode("parent1", "Parent");
session.save();
Node child1 = parent1.addNode("child1", "Child");
assertThat(child1, is(notNullValue()));
session.save();
session.getWorkspace().createWorkspace("clone", "original");
session = repository.login("clone");
Node child2 = session.getNode("/parent1").addNode("child2", "Child");
assertThat(child2, is(notNullValue()));
session.save();
session = repository.login("original");
VersionManager vm = session.getWorkspace().getVersionManager();
NodeIterator ni = vm.merge("/", "clone", true);
session.save();
session.getNode("/parent1/child2");
}, true, true);
}
@Test
public void shouldRemoveMixVersionablePropertiesWhenRemovingMixin() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
Node node = session.getRootNode().addNode("testNode");
node.addMixin(JcrMixLexicon.VERSIONABLE.getString());
session.save();
// mix:referenceable
assertNotNull(node.getProperty(JcrLexicon.UUID.getString()));
// mix:simpleVersionable
assertTrue(node.getProperty(JcrLexicon.IS_CHECKED_OUT.getString()).getBoolean());
// mix:versionable
assertNotNull(node.getProperty(JcrLexicon.BASE_VERSION.getString()));
assertNotNull(node.getProperty(JcrLexicon.VERSION_HISTORY.getString()));
assertNotNull(node.getProperty(JcrLexicon.PREDECESSORS.getString()));
node.removeMixin(JcrMixLexicon.VERSIONABLE.getString());
session.save();
// mix:referenceable
assertPropertyIsAbsent(node, JcrLexicon.UUID.getString());
// mix:simpleVersionable
assertPropertyIsAbsent(node, JcrLexicon.IS_CHECKED_OUT.getString());
// mix:versionable
assertPropertyIsAbsent(node, JcrLexicon.VERSION_HISTORY.getString());
assertPropertyIsAbsent(node, JcrLexicon.BASE_VERSION.getString());
assertPropertyIsAbsent(node, JcrLexicon.PREDECESSORS.getString());
}, true, true);
}
@Test
public void shouldRelinkVersionablePropertiesWhenRemovingAndReaddingMixVersionable() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
JcrVersionManager jcrVersionManager = (JcrVersionManager) versionManager;
Node node = session.getRootNode().addNode("testNode");
node.addMixin(JcrMixLexicon.VERSIONABLE.getString());
session.save();
// create a new version
jcrVersionManager.checkin("/testNode");
jcrVersionManager.checkout("/testNode");
jcrVersionManager.checkin("/testNode");
JcrVersionHistoryNode originalVersionHistory = jcrVersionManager.getVersionHistory("/testNode");
Version originalBaseVersion = jcrVersionManager.getBaseVersion("/testNode");
// remove the mixin
jcrVersionManager.checkout("/testNode");
node.removeMixin(JcrMixLexicon.VERSIONABLE.getString());
session.save();
// re-create the mixin and check the previous version history & versionable properties have been relinked.
node.addMixin(JcrMixLexicon.VERSIONABLE.getString());
session.save();
// mix:referenceable
assertNotNull(node.getProperty(JcrLexicon.UUID.getString()));
// mix:simpleVersionable
assertTrue(node.getProperty(JcrLexicon.IS_CHECKED_OUT.getString()).getBoolean());
// mix:versionable
assertNotNull(node.getProperty(JcrLexicon.BASE_VERSION.getString()));
assertNotNull(node.getProperty(JcrLexicon.VERSION_HISTORY.getString()));
assertNotNull(node.getProperty(JcrLexicon.PREDECESSORS.getString()));
JcrVersionHistoryNode versionHistory = jcrVersionManager.getVersionHistory("/testNode");
Version baseVersion = jcrVersionManager.getBaseVersion("/testNode");
// check the actual
assertEquals(originalVersionHistory.key(), versionHistory.key());
assertEquals(originalBaseVersion.getCreated(), baseVersion.getCreated());
assertEquals(originalBaseVersion.getPath(), baseVersion.getPath());
}, true, true);
}
@Test
public void shouldMergeEventualSuccessorVersions() throws Exception {
// Create a "/record", make it versionable and check it in
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
session.getRootNode().addNode("record").addMixin("mix:versionable");
session.save();
versionManager.checkin("/record");
// Clone QA version of data
session.getWorkspace().createWorkspace("QA", session.getWorkspace().getName());
Session sessionQa = repository.login("QA");
VersionManager versionManagerQa = sessionQa.getWorkspace().getVersionManager();
// Change QA node first time
versionManagerQa.checkout("/record");
sessionQa.getNode("/record").setProperty("111", "111");
sessionQa.save();
versionManagerQa.checkin("/record");
// Change QA node second time
versionManagerQa.checkout("/record");
sessionQa.getNode("/record").setProperty("222", "222");
sessionQa.save();
versionManagerQa.checkin("/record");
// Checks before merge
// Check basic node - should not have any properties
assertFalse(session.getNode("/record").hasProperty("111"));
assertFalse(session.getNode("/record").hasProperty("222"));
// Check QA node - should have properties 111=111 and 222=222
assertTrue(sessionQa.getNode("/record").hasProperty("111"));
assertTrue(sessionQa.getNode("/record").hasProperty("222"));
assertEquals("111", sessionQa.getNode("/record").getProperty("111").getString());
assertEquals("222", sessionQa.getNode("/record").getProperty("222").getString());
// Merge
versionManager.merge("/record", sessionQa.getWorkspace().getName(), true);
// Checks after merge - basic node should have properties 111=111 and 222=222
assertTrue(session.getNode("/record").hasProperty("111"));
assertTrue(session.getNode("/record").hasProperty("222"));
assertEquals("111", session.getNode("/record").getProperty("111").getString());
assertEquals("222", session.getNode("/record").getProperty("222").getString());
sessionQa.logout();
}, true, true);
}
@Test
public void shouldSetMergeFailedPropertyIfNodeIsCheckedIn() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
// Create a record, make it versionable and check it in
session.getRootNode().addNode("record").addMixin("mix:versionable");
session.save();
versionManager.checkin("/record");
// Clone QA version of data
session.getWorkspace().createWorkspace("QA", session.getWorkspace().getName());
Session sessionQa = repository.login("QA");
try {
VersionManager versionManagerQa = sessionQa.getWorkspace().getVersionManager();
// Change QA node first time
versionManagerQa.checkout("/record");
sessionQa.getNode("/record").setProperty("111", "111");
sessionQa.save();
versionManagerQa.checkin("/record");
// Change QA node second time, store version
versionManagerQa.checkout("/record");
sessionQa.getNode("/record").setProperty("222", "222");
sessionQa.save();
Version offendingVersion = versionManagerQa.checkin("/record");
// Change original node one time to make versions in this workspace and other workspace be on
// divergent branches, causing merge() to fail
versionManager.checkout("/record");
session.getNode("/record").setProperty("333", "333");
session.save();
versionManager.checkin("/record");
// Try to merge
NodeIterator nodeIterator = versionManager.merge("/record", sessionQa.getWorkspace().getName(), true);
assertTrue(nodeIterator.hasNext());
while (nodeIterator.hasNext()) {
Node record = nodeIterator.nextNode();
Version mergeFailedVersion = (Version) session.getNodeByIdentifier(record.getProperty("jcr:mergeFailed")
.getValues()[0].getString());
assertEquals(offendingVersion.getIdentifier(), mergeFailedVersion.getIdentifier());
versionManager.cancelMerge("/record", mergeFailedVersion);
assertFalse(record.hasProperty("jcr:mergeFailed"));
}
} finally {
sessionQa.logout();
}
}, true, true);
}
@Test
public void shouldSetMergeFailedPropertyIfNodeIsCheckedIn2() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
// Create a record, make it versionable and check it in
session.getRootNode().addNode("record").addMixin("mix:versionable");
session.save();
versionManager.checkin("/record");
// Clone QA version of data
session.getWorkspace().createWorkspace("QA", session.getWorkspace().getName());
Session sessionQa = repository.login("QA");
try {
VersionManager versionManagerQa = sessionQa.getWorkspace().getVersionManager();
// Change QA node first time, store version
versionManagerQa.checkout("/record");
sessionQa.getNode("/record").setProperty("111", "111");
sessionQa.save();
Version offendingVersion1 = versionManagerQa.checkin("/record");
// Change original node one time to make versions in this workspace and other workspace be on
// divergent branches, causing merge() to fail
versionManager.checkout("/record");
session.getNode("/record").setProperty("333", "333");
session.save();
versionManager.checkin("/record");
// Try to merge with offendingVersion1
// This should create a new jcr:mergeFailed property
versionManager.merge("/record", sessionQa.getWorkspace().getName(), true);
// Change QA node second time, store version
versionManagerQa.checkout("/record");
sessionQa.getNode("/record").setProperty("222", "222");
sessionQa.save();
Version offendingVersion2 = versionManagerQa.checkin("/record");
// Try to merge with offendingVersion2
// This should add to existing jcr:mergeFailed property
NodeIterator nodeIterator = versionManager.merge("/record", sessionQa.getWorkspace().getName(), true);
assertTrue(nodeIterator.hasNext());
while (nodeIterator.hasNext()) {
Node record = nodeIterator.nextNode();
Version mergeFailedVersion1 = (Version) session.getNodeByIdentifier(record.getProperty("jcr:mergeFailed")
.getValues()[0].getString());
assertEquals(offendingVersion1.getIdentifier(), mergeFailedVersion1.getIdentifier());
Version mergeFailedVersion2 = (Version) session.getNodeByIdentifier(record.getProperty("jcr:mergeFailed")
.getValues()[1].getString());
assertEquals(offendingVersion2.getIdentifier(), mergeFailedVersion2.getIdentifier());
versionManager.cancelMerge("/record", mergeFailedVersion1);
versionManager.cancelMerge("/record", mergeFailedVersion2);
assertFalse(record.hasProperty("jcr:mergeFailed"));
}
} finally {
sessionQa.logout();
}
}, true, true);
}
@Test
public void shouldMergeNodesWithSameNamesById() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
// Create a parent and two children, make them versionable and check them in
Node parent = session.getRootNode().addNode("parent");
parent.addMixin("mix:versionable");
Node child1 = parent.addNode("child");
child1.addMixin("mix:versionable");
child1.setProperty("myproperty", "CHANGEME");
Node child2 = parent.addNode("child");
child2.addMixin("mix:versionable");
child2.setProperty("myproperty", "222");
session.save();
versionManager.checkin(parent.getPath());
versionManager.checkin(child1.getPath());
versionManager.checkin(child2.getPath());
// Clone QA version of data
session.getWorkspace().createWorkspace("QA", session.getWorkspace().getName());
Session sessionQa = repository.login("QA");
VersionManager versionManagerQa = sessionQa.getWorkspace().getVersionManager();
try {
// QA: change child1's property
Node qaParent = sessionQa.getNode("/parent");
versionManagerQa.checkout(qaParent.getPath());
Node qaChild1 = sessionQa.getNodeByIdentifier(child1.getIdentifier());
versionManagerQa.checkout(qaChild1.getPath());
qaChild1.setProperty("myproperty", "111");
// QA: Add three new children with same name/path to parent
Node qaChild3 = qaParent.addNode("child");
qaChild3.addMixin("mix:versionable");
qaChild3.setProperty("myproperty", "333");
Node qaChild4 = qaParent.addNode("child");
qaChild4.addMixin("mix:versionable");
qaChild4.setProperty("myproperty", "444");
Node qaChild5 = qaParent.addNode("child");
qaChild5.addMixin("mix:versionable");
qaChild5.setProperty("myproperty", "555");
// QA: drop child2
Node qaChild2 = sessionQa.getNodeByIdentifier(child2.getIdentifier());
qaChild2.remove();
sessionQa.save();
Version qaChild1Version = versionManagerQa.checkin(qaChild1.getPath());
Version qaChild3Version = versionManagerQa.checkin(qaChild3.getPath());
Version qaChild4Version = versionManagerQa.checkin(qaChild4.getPath());
Version qaChild5Version = versionManagerQa.checkin(qaChild5.getPath());
Version qaParentVersion = versionManagerQa.checkin(qaParent.getPath());
// Merge
NodeIterator nodeIterator = versionManager.merge("/parent", sessionQa.getWorkspace().getName(), true);
parent = session.getNodeByIdentifier(parent.getIdentifier());
child1 = session.getNodeByIdentifier(qaChild1.getIdentifier());
try {
session.getNodeByIdentifier(child2.getIdentifier()); // this one got removed
fail("Deleted child should not be retrieved");
} catch (ItemNotFoundException e) {
//continue
}
Node child3 = session.getNodeByIdentifier(qaChild3.getIdentifier());
Node child4 = session.getNodeByIdentifier(qaChild4.getIdentifier());
Node child5 = session.getNodeByIdentifier(qaChild5.getIdentifier());
// Run some checks using default workspace's versionManager and session
assertFalse(nodeIterator.hasNext());
assertEquals(qaParentVersion.getIdentifier(), versionManager.getBaseVersion(qaParent.getPath()).getIdentifier());
assertEquals(qaChild1Version.getIdentifier(), versionManager.getBaseVersion(child1.getPath()).getIdentifier());
assertEquals(qaChild3Version.getIdentifier(), versionManager.getBaseVersion(child3.getPath()).getIdentifier());
assertEquals(qaChild4Version.getIdentifier(), versionManager.getBaseVersion(child4.getPath()).getIdentifier());
assertEquals(qaChild5Version.getIdentifier(), versionManager.getBaseVersion(child5.getPath()).getIdentifier());
// Check that parent no longer has child2
for (NodeIterator childIterator = parent.getNodes(); childIterator.hasNext();) {
Node child = childIterator.nextNode();
assertFalse(child.getIdentifier().equals(child2.getIdentifier()));
}
assertEquals(1, child1.getIndex());
assertEquals(2, child3.getIndex());
assertEquals(3, child4.getIndex());
assertEquals(4, child5.getIndex());
assertEquals("111", child1.getProperty("myproperty").getString());
assertEquals("333", child3.getProperty("myproperty").getString());
assertEquals("444", child4.getProperty("myproperty").getString());
assertEquals("555", child5.getProperty("myproperty").getString());
} finally {
sessionQa.logout();
}
}, true, true);
}
@Test
public void shouldRestoreNodeWithVersionedChildrenUsingCheckpoints() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
// Create a parent and two children, make them versionable and check them in
Node parent = session.getRootNode().addNode("parent");
parent.addMixin("mix:versionable");
Node child1 = parent.addNode("child1");
child1.addMixin("mix:versionable");
child1.setProperty("myproperty", "v1_1");
Node child2 = parent.addNode("child2");
child2.addMixin("mix:versionable");
child2.setProperty("myproperty", "v2_1");
session.save();
Version v1 = versionManager.checkpoint(parent.getPath());
assertEquals("1.0", v1.getName());
child1.setProperty("myproperty", "v1_2");
child2.setProperty("myproperty", "v2_2");
session.save();
Version v2 = versionManager.checkpoint(parent.getPath());
assertEquals("1.1", v2.getName());
versionManager.restore(parent.getPath(), "1.0", true);
parent = session.getNode("/parent");
assertEquals("v1_2", parent.getNode("child1").getProperty("myproperty").getString());
assertEquals("v2_2", parent.getNode("child2").getProperty("myproperty").getString());
}, true, true);
}
@Test
public void shouldRestoreNodeWithoutVersionedChildrenUsingCheckpoints() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
Node node = session.getRootNode().addNode("revert", "jj:page");
node.addNode("child1", "jj:content");
node.addNode("child2", "jj:content");
session.save();
//create two versions
versionManager.checkpoint(node.getPath());
versionManager.checkpoint(node.getPath());
versionManager.restore(node.getPath(), "1.0", true);
}, true, true);
}
@Test
public void shouldNotReturnTheVersionHistoryNode() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
Node node = session.getRootNode().addNode("outerFolder");
node.setProperty("jcr:mimeType", "text/plain");
node.addMixin("mix:versionable");
session.save();
versionManager.checkpoint("/outerFolder");
node.remove();
session.save();
try {
session.getNodeByIdentifier(node.getIdentifier());
fail("Removed versionable node should not be retrieved ");
} catch (ItemNotFoundException e) {
//expected
}
}, true, true);
}
@Test
public void shouldKeepOrderWhenRestoring() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
Node parent = session.getRootNode().addNode("parent", "jj:page");
parent.addNode("child1", "jj:content");
parent.addNode("child2", "jj:content");
parent.addNode("child3", "jj:content");
parent.addNode("child4", "jj:content");
session.save();
versionManager.checkpoint(parent.getPath());
parent = session.getNode("/parent");
parent.orderBefore("child4", "child3");
parent.orderBefore("child3", "child2");
parent.orderBefore("child2", "child1");
session.save();
Version version = versionManager.getBaseVersion(parent.getPath());
versionManager.restore(version, true);
parent = session.getNode("/parent");
List<String> children = new ArrayList<String>();
NodeIterator nodeIterator = parent.getNodes();
while (nodeIterator.hasNext()) {
children.add(nodeIterator.nextNode().getPath());
}
assertEquals(Arrays.asList("/parent/child1", "/parent/child2", "/parent/child3", "/parent/child4"), children);
}, true, true);
}
@Test
public void shouldRestoreAfterRemovingAndReaddingNodesWithSameName() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
Node parent = session.getRootNode().addNode("parent", "jj:page");
Node child = parent.addNode("child", "jj:content");
child.addNode("descendant", "jj:content");
child.addNode("descendant", "jj:content");
session.save();
versionManager.checkpoint(parent.getPath());
child = session.getNode("/parent/child");
NodeIterator childNodes = child.getNodes();
while (childNodes.hasNext()) {
childNodes.nextNode().remove();
}
child.addNode("descendant", "jj:content");
child.addNode("descendant", "jj:content");
session.save();
Version version = versionManager.getBaseVersion(parent.getPath());
versionManager.restore(version, true);
parent = session.getNode("/parent");
assertEquals(Arrays.asList("/parent/child", "/parent/child/descendant", "/parent/child/descendant[2]"),
allChildrenPaths(parent));
}, true, true);
}
@Test
public void shouldRestoreMovedNode() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
Node parent = session.getRootNode().addNode("parent", "jj:page");
parent.addNode("child", "jj:content");
session.save();
versionManager.checkpoint(parent.getPath());
parent.addNode("_context", "jj:context");
// move to a location under a new parent
session.move("/parent/child", "/parent/_context/child");
session.save();
// restore
versionManager.restore(parent.getPath(), "1.0", true);
//the default OPV is COPY, so we expect the restore to have removed _context
assertNoNode(session, "/parent/_context");
assertNode(session, "parent/child");
}, true, true);
}
@Test
public void shouldRestoreToMultipleVersionsWhenEachVersionHasDifferentChild() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
// Add a page node with one child then make a version 1.0
Node node = session.getRootNode().addNode("page", "jj:page");
node.addNode("child1", "jj:content");
session.save();
versionManager.checkpoint(node.getPath());
// add second child then make version 1.1
node.addNode("child2", "jj:content");
session.save();
versionManager.checkpoint(node.getPath());
// restore to 1.0
versionManager.restore(node.getPath(), "1.0", true);
assertNode(session, "page/child1");
assertNoNode(session, "/page/child2");
// then restore to 1.1, it will throw the NullPointException
versionManager.restore(node.getPath(), "1.1", true);
assertNode(session, "page/child1");
assertNode(session, "page/child2");
}, true, true);
}
@Test
public void shouldRestoreMovedNode2() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
Node parent = session.getRootNode().addNode("parent", "jj:page");
parent.addNode("_context", "jj:context");
parent.addNode("child", "jj:content");
session.save();
versionManager.checkpoint(parent.getPath());
// move to a location under a new parent
session.move("/parent/child", "/parent/_context/child");
session.save();
// restore
versionManager.restore(parent.getPath(), "1.0", true);
assertNoNode(session, "/parent/_context/child");
assertNode(session, "parent/child");
}, true, true);
}
@Test
public void shouldRestoreMovedNode3() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
Node parent = session.getRootNode().addNode("parent", "jj:page");
parent.addNode("child1", "jj:content");
parent.addNode("_context", "jj:context");
parent.addNode("child2", "jj:content");
session.save();
versionManager.checkpoint(parent.getPath());
// move to a location under a new parent
session.move("/parent/child1", "/parent/_context/child1");
session.save();
// restore
versionManager.restore(parent.getPath(), "1.0", true);
assertNoNode(session, "/parent/_context/child1");
assertNoNode(session, "/parent/_context/child2");
assertNode(session, "parent/child1");
assertNode(session, "parent/child2");
assertNode(session, "parent/_context");
}, true, true);
}
@Test
public void shouldRemoveVersionInVersionGraphWithBranches1() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
Node node = session.getRootNode().addNode("node", "jj:page");
session.save();
Version v1 = versionManager.checkpoint(node.getPath());
assertEquals("1.0", v1.getName());
assertEquals(2, versionManager.getVersionHistory("/node").getAllVersions().getSize());
Version v2 = versionManager.checkin("/node");
assertEquals("1.1", v2.getName());
assertEquals(3, versionManager.getVersionHistory("/node").getAllVersions().getSize());
versionManager.restore(v1, true);
assertEquals(3, versionManager.getVersionHistory("/node").getAllVersions().getSize());
Version baseVersion = versionManager.checkpoint(node.getPath());
assertEquals("1.0", baseVersion.getName());
assertEquals(3, versionManager.getVersionHistory("/node").getAllVersions().getSize());
Version v4 = versionManager.checkin("/node");
assertEquals("1.1.0", v4.getName());
assertEquals(4, versionManager.getVersionHistory("/node").getAllVersions().getSize());
versionManager.getVersionHistory("/node").removeVersion(v1.getName());
}, true, true);
}
@Test
public void shouldRemoveVersionInVersionGraphWithBranches2() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
Node node = session.getRootNode().addNode("node", "jj:page");
session.save();
String nodePath = node.getPath();
//create two versions
versionManager.checkpoint(nodePath); // version 1.0
versionManager.checkpoint(nodePath); // version 1.1
versionManager.restore(nodePath, "1.0", true);
versionManager.checkout(nodePath);
versionManager.checkpoint(nodePath); // version 1.1.0
versionManager.getVersionHistory(nodePath).removeVersion("1.1");
}, true, true);
}
@Test
public void shouldRemoveEmptyVersionHistories() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
Node node1 = session.getRootNode().addNode("node1", "jj:page");
node1.addNode("node11", "jj:page");
node1.addNode("node12", "jj:content");
session.save();
((org.modeshape.jcr.api.version.VersionManager) versionManager).remove("/node1");
try {
versionManager.getVersionHistory("/node1");
fail("Version history has not been removed");
} catch (PathNotFoundException e) {
//expected
}
try {
versionManager.getVersionHistory("/node1/node11");
fail("Version history has not been removed");
} catch (PathNotFoundException e) {
//expected
}
}, true, true);
}
@Test
public void shouldNotRemoveNonEmptyVersionHistories() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.versionManager();
Node node1 = session.getRootNode().addNode("node1", "jj:page");
node1.addNode("node11", "jj:page");
session.save();
versionManager.checkpoint("/node1/node11");
try {
((org.modeshape.jcr.api.version.VersionManager) versionManager).remove("/node1");
fail("Should not allow removal of non empty version history");
} catch (UnsupportedRepositoryOperationException e) {
//expected
}
}, true, true);
}
@Test
public void shouldCreateSeparateVersionHistoryForCopiedNode() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.getWorkspace().getVersionManager();
// create original node
Node node = session.getNode("/").addNode("uploads");
Node originalNode = node.addNode("originalNode", NodeType.NT_FILE);
originalNode.addMixin(NodeType.MIX_VERSIONABLE);
originalNode.addMixin(NodeType.MIX_TITLE);
Node contentNode = originalNode.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_RESOURCE);
contentNode.setProperty(JcrConstants.JCR_DATA,
session.getValueFactory().createBinary(new ByteArrayInputStream("test".getBytes())));
session.save();
// update original node
versionManager.checkout(originalNode.getPath());
originalNode.setProperty(Property.JCR_TITLE, "originalNode");
session.save();
versionManager.checkin(originalNode.getPath());
VersionHistory originalHistory = versionManager.getVersionHistory(originalNode.getPath());
Version originalBaseVersion = versionManager.getBaseVersion(originalNode.getPath());
// copy original node
session.getWorkspace().copy(originalNode.getPath(), "/uploads/copiedNode");
// check that the copied node is checked out and has its own version history
Node copiedNode = session.getNode("/uploads/copiedNode");
assertTrue(versionManager.isCheckedOut(copiedNode.getPath()));
VersionHistory copiedHistory = versionManager.getVersionHistory(copiedNode.getPath());
assertNotEquals(originalHistory.getVersionableIdentifier(), copiedHistory.getVersionableIdentifier());
Version copiedBaseVersion = versionManager.getBaseVersion(copiedNode.getPath());
assertNotEquals(originalBaseVersion.getPath(), copiedBaseVersion.getPath());
// delete all versions for the original node
VersionIterator it = originalHistory.getAllVersions();
while (it.hasNext()) {
Version version = it.nextVersion();
originalHistory.removeVersion(version.getName());
}
// delete all versions for the copied node
it = copiedHistory.getAllVersions();
while (it.hasNext()) {
Version version = it.nextVersion();
copiedHistory.removeVersion(version.getName());
}
// delete original node
originalNode.remove();
session.save();
// delete the copied node
copiedNode.remove();
session.save();
}, true, true);
}
@Test
public void shouldReadChildVersionHistoryProperty() throws Exception {
startRunStop(repository -> {
JcrSession session = (JcrSession) repository.login();
VersionManager versionManager = session.getWorkspace().getVersionManager();
// Create a versionable parent node and add a single version.
Node parentNode = session.getRootNode().addNode("parent");
parentNode.addMixin("mix:versionable");
session.save();
VersionManager vm = parentNode.getSession().getWorkspace().getVersionManager();
vm.checkout(parentNode.getPath());
vm.checkin(parentNode.getPath());
vm.checkout(parentNode.getPath());
// Create a versionable child node for a previously created parent and add a single version.
Node childNode = parentNode.addNode("child");
childNode.addMixin("mix:versionable");
session.save();
vm.checkout(childNode.getPath());
vm.checkin(childNode.getPath());
vm.checkin(parentNode.getPath());
// Obtain the base version of the parent node.
Version baseParentVersion = vm.getBaseVersion(parentNode.getPath());
Node frozenNode = baseParentVersion.getFrozenNode();
NodeIterator nodeIterator = frozenNode.getNodes();
while (nodeIterator.hasNext()) {
Node child = nodeIterator.nextNode();
assertThat(child.getProperty("jcr:primaryType").getString(), is("nt:versionedChild"));
Property property = child.getProperty("jcr:childVersionHistory");
VersionHistory versionHistory = (VersionHistory) property.getNode();
// Do something about obtained version history...
assertNotNull(versionHistory);
}
}, true, true);
}
/**--------------------------------------------------------------------------*/
// @Test
public void shouldBackupRepositoryWhichIncludesBinaryValuesCompressed() throws Exception {
startRunStop(repository -> {
JcrSession session = repository.login();
loadBinaries(session);
}, true, false);
startRunStop(repository -> {
JcrSession session = repository.login();
session.getWorkspace().createWorkspace("ws2");
session.getWorkspace().createWorkspace("ws3");
session = repository.login("ws2");
loadBinaries(session);
session = repository.login("ws3");
loadBinaries(session);
}, false, false);
startRunStop(repository -> {
JcrSession session = repository.login();
makeBackup(session, BackupOptions.DEFAULT);
}, false, true);
this.restoreBackup(true);
startRunStop(repository -> {
JcrSession session = repository.login();
verifyBinaryContent(session);
session = repository.login("ws2");
verifyBinaryContent(session);
session = repository.login("ws3");
verifyBinaryContent(session);
}, false, true);
}
@Test
public void shouldBackupRepositoryWhichIncludesBinaryValuesUnCompressed() throws Exception {
startRunStop(repository -> {
JcrSession session = repository.login();
loadBinaries(session);
}, true, false);
startRunStop(repository -> {
JcrSession session = repository.login();
session.getWorkspace().createWorkspace("ws2");
session.getWorkspace().createWorkspace("ws3");
session = repository.login("ws2");
loadBinaries(session);
session = repository.login("ws3");
loadBinaries(session);
}, false, false);
startRunStop(repository -> {
JcrSession session = repository.login();
BackupOptions backupOptions = new BackupOptions() {
@Override
public boolean compress() {
return false;
}
};
makeBackup(session, backupOptions);
}, false, true);
this.restoreBackup(true);
startRunStop(repository -> {
JcrSession session = repository.login();
verifyBinaryContent(session);
session = repository.login("ws2");
verifyBinaryContent(session);
session = repository.login("ws3");
verifyBinaryContent(session);
}, false, true);
}
@Test
public void shouldPreserveBinariesFromRestoredBackup() throws Exception {
startRunStop(repository -> {
JcrSession session = repository.login();
loadBinaries(session);
makeBackup(session, BackupOptions.DEFAULT);
}, true, false);
//wipe the repository
startRunStop(repository -> {
JcrSession session = repository.login();
}, true, true);
this.restoreBackup(true);
startRunStop(repository -> {
JcrSession session = repository.login();
makeBackup(session, BackupOptions.DEFAULT);
}, false, false);
//wipe the repository
startRunStop(repository -> {
JcrSession session = repository.login();
}, true, true);
this.restoreBackup(true);
startRunStop(repository -> {
JcrSession session = repository.login();
verifyBinaryContent(session);
}, false, true);
}
@Test
public void shouldBackupRepositoryWithMultipleWorkspaces() throws Exception {
startRunStop(repository -> {
JcrSession session = repository.login();
session.getWorkspace().createWorkspace("ws2");
session.getWorkspace().createWorkspace("ws3");
session = repository.login("ws2");
importInitialContent("data/cars.xml", session);
session = repository.login("ws3");
importInitialContent("data/cars.xml", session);
session = repository.login();
makeBackup(session, BackupOptions.DEFAULT);
// Make some changes that will not be in the backup ...
session.getRootNode().addNode("node-not-in-backup");
session.save();
assertContentInWorkspace(session, "/node-not-in-backup");
session = repository.login("ws2");
assertContentInWorkspace(session);
session = repository.login("ws3");
assertContentInWorkspace(session);
}, true, false);
this.restoreBackup(true);
startRunStop(repository -> {
JcrSession session = repository.login();
assertContentNotInWorkspace(session, "/node-not-in-backup");
assertContentInWorkspace(session);
session = repository.login("ws2");
assertContentInWorkspace(session);
session = repository.login("ws3");
assertContentInWorkspace(session);
}, false, true);
}
@Test
public void shouldBackupAndRestoreWithExistingUserTransaction() throws Exception {
startRunStop(repository -> {
JcrSession session = repository.login();
TransactionManager txnMgr = repository.transactionManager();
txnMgr.begin();
makeBackup(session, BackupOptions.DEFAULT);
restoreBackup(false);
txnMgr.rollback();
assertContentInWorkspace(session);
}, true, true);
}
@Test
public void shouldRestoreBinaryReferencesWhenExcludedFromBackup() throws Exception {
startRunStop(repository -> {
JcrSession session = repository.login();
loadBinaries(session);
BackupOptions backupOptions = new BackupOptions() {
@Override
public boolean includeBinaries() {
return false;
}
};
makeBackup(session, backupOptions);
}, true, false);
//wipe the repository
startRunStop(repository -> {
JcrSession session = repository.login();
}, true, true);
RestoreOptions restoreOptions = new RestoreOptions() {
@Override
public boolean includeBinaries() {
return false;
}
};
this.restoreBackup(restoreOptions);
startRunStop(repository -> {
JcrSession session = repository.login();
verifyBinaryContent(session);
}, false, true);
}
@Test
public void shouldPersistGeneratedNamespacesAcrossRestart() throws Exception {
startRunStop(repository -> {
Session session = repository.login();
final NamespaceRegistry namespaceRegistry = (NamespaceRegistry)session.getWorkspace().getNamespaceRegistry();
namespaceRegistry.registerNamespace("info:a#");
namespaceRegistry.registerNamespace("info:b#");
namespaceRegistry.registerNamespace("info:c#");
assertEquals("ns001", namespaceRegistry.getPrefix("info:a#"));
assertEquals("ns002", namespaceRegistry.getPrefix("info:b#"));
assertEquals("ns003", namespaceRegistry.getPrefix("info:c#"));
final Node node = session.getRootNode().addNode("ns001:xyz", NodeType.NT_UNSTRUCTURED);
node.setProperty("ns002:abc", "abc");
node.setProperty("ns003:def", "def");
session.save();
session.logout();
}, true, false);
startRunStop(repository -> {
Session session = repository.login();
final NamespaceRegistry namespaceRegistry = (NamespaceRegistry)session.getWorkspace().getNamespaceRegistry();
assertEquals("ns001", namespaceRegistry.getPrefix("info:a#"));
assertEquals("ns002", namespaceRegistry.getPrefix("info:b#"));
assertEquals("ns003", namespaceRegistry.getPrefix("info:c#"));
session.save();
session.logout();
}, false, true);
}
@Test
public void shouldPersistDataAcrossRestart() throws Exception {
startRunStop(repository -> {
JcrSession session = repository.login();
loadBinaries(session);
session.getWorkspace().createWorkspace("ws2");
session.save();
session = repository.login("ws2");
importInitialContent("data/cars.xml", session);
session.save();
}, true, false);
startRunStop(repository -> {
JcrSession session = repository.login("ws2");
assertContentInWorkspace(session);
Node node = session.getNode("/a/b/Cars/Utility/Ford F-150");
node.setProperty("car:year", "2009");
session.save();
}, false, false);
startRunStop(repository -> {
JcrSession session = repository.login("ws2");
Node node = session.getNode("/a/b/Cars/Utility/Ford F-150");
assertEquals("2009", node.getProperty("car:year").getString());
node.remove();
session.save();
}, false, false);
startRunStop(repository -> {
JcrSession session = repository.login("ws2");
assertContentNotInWorkspace(session, "/a/b/Cars/Utility/Ford F-150");
}, false, false);
startRunStop(repository -> {
JcrSession session = repository.login();
verifyBinaryContent(session);
}, false, true);
}
@Test
public void shouldPersistBinaryDataAcrossRestart() throws Exception {
startRunStop(repository -> {
JcrSession session = repository.login();
loadBinaries(session);
session.save();
}, true, false);
startRunStop(repository -> {
JcrSession session = repository.login();
verifyBinaryContent(session);
}, false, true);
}
@Test
public void shouldPersistSequence() throws Exception {
startRunStop(repository -> {
org.modeshape.jcr.api.Session session = repository.login();
InputStream stream = getClass().getClassLoader().getResourceAsStream("log4j.properties");
Node node = session.getRootNode().addNode("log4j.properties", "nt:file");
Node content = node.addNode("jcr:content", "nt:resource");
content.setProperty("jcr:data", session.getValueFactory().createBinary(stream));
Node output = session.getRootNode().addNode("output");
assertFalse(output.hasNode(TestSequencersHolder.DERIVED_NODE_NAME));
session.sequence("Counting sequencer", content.getProperty("jcr:data"), output);
assertTrue(output.hasNode(TestSequencersHolder.DERIVED_NODE_NAME));
session.save();
}, true, false);
startRunStop(repository -> {
Session session = repository.login();
Node output = session.getNode("/output");
assertTrue(output.hasNode(TestSequencersHolder.DERIVED_NODE_NAME));
}, false, true);
}
@Test
@FixFor( "MODE-2607" )
public void shouldUpdateParentAndRemoveChildWithDifferentTransactions1() throws Exception {
startRunStop(repository -> {
final String parentPath = "/parent";
final String childPath = "/parent/child";
TransactionManager txManager = repository.transactionManager();
//create parent and child node with some properties in a tx
txManager.begin();
JcrSession session = repository.login();
Node parent = session.getRootNode().addNode("parent");
parent.setProperty("foo", "parent");
Node child = parent.addNode("child");
child.setProperty("foo", "child");
session.save();
txManager.commit();
//edit the parent and remove the child in a new tx
txManager.begin();
session = repository.login();
parent = session.getNode(parentPath);
parent.setProperty("foo", "bar2");
session.save();
child = session.getNode(childPath);
child.remove();
session.save();
txManager.commit();
//check that the editing worked in a new tx
txManager.begin();
parent = session.getNode(parentPath);
assertEquals("bar2", parent.getProperty("foo").getString());
assertNoNode(session, "/parent/child");
txManager.commit();
}, true, true);
}
@Test
@FixFor( "MODE-2610" )
public void shouldUpdateParentAndRemoveChildWithDifferentTransactions2() throws Exception {
startRunStop(repository -> {
final String parentPath = "/parent";
final String childPath = "/parent/child";
JcrSession session = repository.login();
TransactionManager txManager = repository.transactionManager();
txManager.begin();
Node parent = session.getRootNode().addNode("parent");
parent.setProperty("foo", "parent");
Node child = parent.addNode("child");
child.setProperty("foo", "child");
session.save();
txManager.commit();
txManager.begin();
child = session.getNode(childPath);
parent = session.getNode(parentPath);
parent.setProperty("foo", "bar2");
session.save();
child.remove();
session.save();
txManager.commit();
txManager.begin();
parent = session.getNode(parentPath);
assertEquals("bar2", parent.getProperty("foo").getString());
assertNoNode(session, "/parent/child");
session.logout();
txManager.commit();
}, true, true);
}
@FixFor( "MODE-2623" )
@Test
public void shouldAllowLockUnlockWithinTransaction() throws Exception {
startRunStop(repository -> {
JcrSession session = repository.login();
TransactionManager txManager = repository.transactionManager();
final String path = "/test";
Node parent = session.getRootNode().addNode("test");
parent.addMixin("mix:lockable");
session.save();
txManager.begin();
LockManager lockMgr = session.getWorkspace().getLockManager();
lockMgr.lock(path, true, true, Long.MAX_VALUE, session.getUserID());
lockMgr.unlock(path);
txManager.commit();
assertFalse(session.getNode(path).isLocked());
}, true, true);
}
protected void startRunStop(RepositoryOperation operation,
boolean createOnStart, boolean dropOnExit) {
JcrRepository repository = null;
try {
testRepository.setDropOnExit(dropOnExit);
testRepository.setCreateOnStart(createOnStart);
testRepository.start();
repository = (JcrRepository) testRepository.repository();
operation.execute(repository);
} catch (RuntimeException re) {
throw re;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (repository != null) {
testRepository.shutdown();
}
}
}
@FunctionalInterface
protected interface RepositoryOperation {
void execute(JcrRepository repository) throws Exception;
}
protected AccessControlList getACL(AccessControlManager acm,
String absPath) throws Exception {
AccessControlPolicyIterator it = acm.getApplicablePolicies(absPath);
if (it.hasNext()) {
return (AccessControlList) it.nextAccessControlPolicy();
}
return (AccessControlList) acm.getPolicies(absPath)[0];
}
private boolean hasVersionHistory(VersionManager versionManager, Node node) throws RepositoryException {
try {
VersionHistory history = versionManager.getVersionHistory(node.getPath());
assertNotNull(history);
return true;
} catch (UnsupportedRepositoryOperationException e) {
return false;
}
}
private void assertPropertyIsAbsent(Node node,
String propertyName) throws Exception {
try {
node.getProperty(propertyName);
fail("Property: " + propertyName + " was expected to be missing on node:" + node);
} catch (PathNotFoundException e) {
// expected
}
}
private List<String> allChildrenPaths(Node root) throws Exception {
List<String> paths = new ArrayList<String>();
NodeIterator nodeIterator = root.getNodes();
while (nodeIterator.hasNext()) {
Node child = nodeIterator.nextNode();
paths.add(child.getPath());
paths.addAll(allChildrenPaths(child));
}
return paths;
}
protected void assertNoNode(JcrSession session, String path) throws RepositoryException {
// Verify that the parent node does exist now ...
assertThat("Did not expect to find '" + path + "'", session.getRootNode().hasNode(relativePath(path)), is(false));
try {
session.getNode(path);
fail("Did not expect to find node at \"" + path + "\"");
} catch (PathNotFoundException e) {
// expected
}
}
protected Node assertNode(JcrSession session, String path) throws RepositoryException {
if (!session.getRootNode().hasNode(path)) {
// We won't find the node, so print out the information ...
Node parent = session.getRootNode();
for (Path.Segment segment : path(session, path)) {
if (!parent.hasNode(asString(session, segment))) {
System.out.println("Unable to find '" + path + "'; lowest node is '" + parent.getPath() + "'");
break;
}
parent = parent.getNode(asString(session, segment));
}
}
Node node = session.getNode("/" + path);
assertThat(node, is(notNullValue()));
// Verify that the path can be found via navigating ...
if (path.trim().length() == 0) {
// This is the root path, so of course it exists ...
assertThat(session.getRootNode(), is(notNullValue()));
} else {
}
return node;
}
protected Path path(JcrSession session, String path) {
return session.context().getValueFactories().getPathFactory().create(path);
}
protected String relativePath(String path) {
return !path.startsWith("/") ? path : path.substring(1);
}
protected String asString(JcrSession session, Object value) {
return session.context().getValueFactories().getStringFactory().create(value);
}
protected void loadBinaries(Session session) throws Exception {
for (int i = 0; i < BINARY_RESOURCES.length; i++) {
String name = "file_" + i;
Node fileNode = session.getRootNode().addNode(name, "nt:file");
Node content = fileNode.addNode("jcr:content", "nt:resource");
InputStream stream = ModeshapePersistenceIT.class.getClassLoader().getResourceAsStream(BINARY_RESOURCES[i]);
content.setProperty("jcr:data", session.getValueFactory().createBinary(stream));
}
session.save();
}
private void makeBackup(JcrSession session, BackupOptions options) throws RepositoryException {
FileUtil.delete(backupDirectory.getPath());
Problems problems = session.getWorkspace().getRepositoryManager().backupRepository(backupDirectory, options);
assertNoProblems(problems);
}
private void restoreBackup(boolean shutdownRepository) throws Exception {
testRepository.setCreateOnStart(true);
testRepository.setDropOnExit(false);
testRepository.start();
try {
JcrSession session = (JcrSession) testRepository.login();
Problems problems = session.getWorkspace().getRepositoryManager().restoreRepository(backupDirectory);
assertNoProblems(problems);
session.logout();
} finally {
if (shutdownRepository) {
testRepository.shutdown();
}
}
}
private void restoreBackup(RestoreOptions opts) throws Exception {
testRepository.setCreateOnStart(true);
testRepository.setDropOnExit(false);
testRepository.start();
try {
JcrSession session = (JcrSession) testRepository.login();
Problems problems = session.getWorkspace().getRepositoryManager().restoreRepository(backupDirectory, opts);
assertNoProblems(problems);
session.logout();
} finally {
testRepository.shutdown();
}
}
protected void assertNoProblems( Problems problems ) {
if (problems.hasProblems()) {
System.out.println(problems);
}
assertThat(problems.hasProblems(), is(false));
}
private void verifyBinaryContent(JcrSession session) throws Exception {
for (int i = 0; i < BINARY_RESOURCES.length; i++) {
String fileName = "/file_" + i;
Node file = session.getNode(fileName).getNode("jcr:content");
Binary binary = file.getProperty("jcr:data").getBinary();
assertNotNull(binary);
InputStream in = getClass().getClassLoader().getResourceAsStream(BINARY_RESOURCES[i]);
byte[] expectedContent = IoUtil.readBytes(in);
byte[] actualContent = IoUtil.readBytes(binary.getStream());
assertArrayEquals("Binary content to valid for " + fileName, expectedContent, actualContent);
}
}
private void assertContentInWorkspace(JcrSession session, String... paths) throws RepositoryException {
session.getRootNode();
session.getNode("/a/b/Cars");
session.getNode("/a/b/Cars/Hybrid");
session.getNode("/a/b/Cars/Hybrid/Toyota Prius");
session.getNode("/a/b/Cars/Hybrid/Toyota Highlander");
session.getNode("/a/b/Cars/Hybrid/Nissan Altima");
session.getNode("/a/b/Cars/Sports/Aston Martin DB9");
session.getNode("/a/b/Cars/Sports/Infiniti G37");
session.getNode("/a/b/Cars/Luxury/Cadillac DTS");
session.getNode("/a/b/Cars/Luxury/Bentley Continental");
session.getNode("/a/b/Cars/Luxury/Lexus IS350");
session.getNode("/a/b/Cars/Utility/Land Rover LR2");
session.getNode("/a/b/Cars/Utility/Land Rover LR3");
session.getNode("/a/b/Cars/Utility/Hummer H3");
session.getNode("/a/b/Cars/Utility/Ford F-150");
for (String path : paths) {
session.getNode(path);
}
}
private void assertContentNotInWorkspace(JcrSession session, String... paths) throws RepositoryException {
session.getRootNode();
for (String path : paths) {
try {
session.getNode(path);
fail("Should not have found '" + path + "'");
} catch (PathNotFoundException e) {
// expected
}
}
}
private void importInitialContent(String resourceName, Session session) throws RepositoryException, IOException {
testRepository.loadInitialContent(resourceName, session);
}
private void cleanDatabase() {
Connection conn = null;
try {
String driverName = System.getProperty("db.driver");
String username = System.getProperty("db.username");
String password = System.getProperty("db.password");
String url = System.getProperty("db.url");
Class.forName(driverName);
conn = DriverManager.getConnection(url, username, password);
Statement deleteQuery = conn.createStatement();
deleteQuery.executeQuery("drop table MODESHAPE_REPOSITORY");
} catch (ClassNotFoundException | SQLException e) {
} finally {
if (conn != null)
try {
conn.close();
} catch (SQLException e) {
}
}
}
}